/**
 * @file log_utils.h
 * @brief 统一日志系统头文件
 * 
 * 提供统一的日志记录功能，支持不同日志级别、控制台输出。
 * 需要写入文件的日志通过UDP套接字发送到日志服务线程。
 * 
 * @author 伞控无人机项目组
 * @date 2024
 */

#ifndef LOG_UTILS_H
#define LOG_UTILS_H

#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <pthread.h>
#include <stdint.h>

// 引入统一的模块命名规范
#include "log_modules.h"

// UDP日志传输配置
#define LOG_UDP_PORT 12345       // UDP端口
#define LOG_UDP_BUFFER_SIZE (5 * 1024 * 1024)  // 5MB缓冲区

// 日志文件开关宏定义
#define LOG_TO_FILE 1            // 通过UDP发送到日志服务线程
#define LOG_TO_CONSOLE_ONLY 0    // 仅控制台输出

// 控制台输出控制
#define LOG_CONSOLE_AUTO 0       // 自动检测（推荐）
#define LOG_CONSOLE_FORCE_ON 1   // 强制开启控制台输出
#define LOG_CONSOLE_FORCE_OFF 2  // 强制关闭控制台输出

// 日志级别定义
typedef enum {
    LOG_LEVEL_FATAL = 0,  // 致命错误，导致程序退出的严重问题
    LOG_LEVEL_ERROR = 1,  // 错误信息，不会导致程序退出但会影响功能
    LOG_LEVEL_WARN  = 2,  // 警告信息，可能存在问题但不影响主要功能
    LOG_LEVEL_INFO  = 3,  // 普通信息，程序正常运行的状态信息
    LOG_LEVEL_DEBUG = 4,  // 调试信息，用于开发调试
    LOG_LEVEL_TRACE = 5   // 跟踪信息，更详细的调试信息
} log_level_t;

// 日志颜色定义（ANSI转义序列）
#define LOG_COLOR_RESET   "\033[0m"
#define LOG_COLOR_FATAL   "\033[1;31m"  // 亮红色
#define LOG_COLOR_ERROR   "\033[31m"    // 红色
#define LOG_COLOR_WARN    "\033[33m"    // 黄色
#define LOG_COLOR_INFO    "\033[32m"    // 绿色
#define LOG_COLOR_DEBUG   "\033[36m"    // 青色
#define LOG_COLOR_TRACE   "\033[35m"    // 紫色

// 日志模块标识最大长度
#define LOG_MODULE_NAME_MAX_LEN 16

// 内存泄漏检测宏
#ifdef MEMORY_LEAK_DETECTION
    #define TRACK_MALLOC(ptr, size, file, line) \
        memory_track_alloc(ptr, size, file, line)
    #define TRACK_FREE(ptr) \
        memory_track_free(ptr)
    #define MEMORY_REPORT() \
        memory_report_usage()
#else
    #define TRACK_MALLOC(ptr, size, file, line) ((void)0)
    #define TRACK_FREE(ptr) ((void)0)
    #define MEMORY_REPORT() ((void)0)
#endif

// 内存跟踪函数声明
void memory_track_alloc(void *ptr, size_t size, const char *file, int line);
void memory_track_free(void *ptr);
void memory_report_usage(void);
void memory_init_tracking(void);
void memory_cleanup_tracking(void);

// 边界检查宏
#define SAFE_ARRAY_ACCESS(array, index, max_size) \
    ((index) >= 0 && (index) < (max_size) ? &(array)[index] : NULL)

#define VALIDATE_BUFFER_SIZE(buffer, size, required) \
    do { \
        if ((size) < (required)) { \
            LOG_ERROR(LOG_TO_FILE, LOG_MODULE_MAIN, \
                     "缓冲区大小不足: %zu < %zu", (size), (required)); \
            return -1; \
        } \
    } while(0)

#define SAFE_STRING_COPY(dest, dest_size, src) \
    safe_string_copy(dest, dest_size, src)

// 安全的数组访问函数
void* safe_array_access(void *array, size_t element_size, int index, int max_size);
int safe_buffer_validate(size_t buffer_size, size_t required_size);

// 日志系统初始化
// 返回：0-成功，-1-失败
int log_init(void);

// 设置日志级别
// 参数：level - 日志级别
void log_set_level(log_level_t level);

// 获取当前日志级别
// 返回：当前日志级别
log_level_t log_get_level(void);

// 设置控制台输出模式
// 参数：mode - 控制台输出模式（LOG_CONSOLE_AUTO/FORCE_ON/FORCE_OFF）
void log_set_console_mode(int mode);

// 获取当前控制台输出模式
// 返回：当前控制台输出模式
int log_get_console_mode(void);

// 记录日志信息
// 参数：to_file - 是否发送到日志服务线程，1表示发送，0表示仅控制台输出
//       level - 日志级别
//       module - 模块名称，用于标识日志来源（建议使用log_modules.h中定义的标准名称）
//       file - 源文件名
//       line - 行号
//       func - 函数名
//       format - 格式化字符串
//       ... - 可变参数
void log_message(int to_file, log_level_t level, const char *module, const char *file, 
                int line, const char *func, const char *format, ...);

// 日志系统清理
void log_cleanup(void);

// 日志宏定义，方便调用
// 第一个参数为是否发送到日志服务线程：LOG_TO_FILE 或 LOG_TO_CONSOLE_ONLY
// 第二个参数为模块名称，建议使用log_modules.h中定义的标准名称
#define LOG_FATAL(to_file, module, format, ...) \
    log_message(to_file, LOG_LEVEL_FATAL, module, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__)

#define LOG_ERROR(to_file, module, format, ...) \
    log_message(to_file, LOG_LEVEL_ERROR, module, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__)

#define LOG_WARN(to_file, module, format, ...) \
    log_message(to_file, LOG_LEVEL_WARN, module, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__)

#define LOG_INFO(to_file, module, format, ...) \
    log_message(to_file, LOG_LEVEL_INFO, module, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__)

#define LOG_DEBUG(to_file, module, format, ...) \
    log_message(to_file, LOG_LEVEL_DEBUG, module, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__)

#define LOG_TRACE(to_file, module, format, ...) \
    log_message(to_file, LOG_LEVEL_TRACE, module, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__)

// ============================================================================
// 模块命名规范使用指南 - 面向日志解析优化
// ============================================================================

/*
推荐的模块命名使用方式（便于后期日志解析软件处理）：

1. 使用标准模块名（推荐）：
   LOG_ERROR(LOG_TO_FILE, LOG_MODULE_NAV, "GPS信号丢失");
   LOG_WARN(LOG_TO_FILE, LOG_MODULE_WIND, "风速超过安全阈值: %.1f m/s", wind_speed);
   LOG_INFO(LOG_TO_FILE, LOG_MODULE_MAIN, "系统启动完成");

2. 使用标准化数据记录宏（强烈推荐，便于解析）：
   LOG_DATA_RECORD(LOG_MODULE_GPS, LOG_DATA_GPS_POS, "lat=%.8f,lon=%.8f,alt=%.2f", lat, lon, alt);
   LOG_DATA_RECORD(LOG_MODULE_IMU, LOG_DATA_IMU_ATT, "roll=%.3f,pitch=%.3f,yaw=%.3f", r, p, y);
   LOG_DATA_RECORD(LOG_MODULE_WIND, LOG_DATA_WIND_SPD, "speed=%.2f", wind_speed);
   LOG_DATA_RECORD(LOG_MODULE_TEMP, LOG_DATA_TEMP_VAL, "temperature=%.1f", temp);

3. 控制指令记录：
   LOG_CMD_RECORD(LOG_MODULE_MOTOR, LOG_CMD_MOTOR_SPD, "motor_id=%d,speed=%d", id, speed);
   LOG_CMD_RECORD(LOG_MODULE_SERVO, LOG_CMD_SERVO_ANG, "servo_id=%d,angle=%.1f", id, angle);

4. 状态信息记录：
   LOG_STATE_RECORD(LOG_MODULE_MAIN, LOG_STATE_SYS_STAT, "status=running,uptime=%d", uptime);
   LOG_STATE_RECORD(LOG_MODULE_TCP, LOG_STATE_CONN_STAT, "clients=%d,active=%d", total, active);

5. 性能统计记录：
   LOG_PERF_RECORD(LOG_MODULE_NAV, "update_rate", update_hz, "Hz");
   LOG_PERF_RECORD(LOG_MODULE_PROC, "process_time", proc_ms, "ms");

6. 错误统计记录：
   LOG_ERROR_STAT(LOG_MODULE_GPS, "timeout", timeout_count);
   LOG_ERROR_STAT(LOG_MODULE_CAN, "frame_error", error_count);

日志级别使用建议（考虑文件大小和解析需求）：
- FATAL/ERROR: 必须使用 LOG_TO_FILE，确保重要错误被记录
- WARN: 重要警告使用 LOG_TO_FILE，一般警告可用 LOG_TO_CONSOLE_ONLY
- INFO: 关键状态变化和传感器数据使用 LOG_TO_FILE
- DEBUG/TRACE: 通常使用 LOG_TO_CONSOLE_ONLY，避免文件过大

模块命名规范优势：
1. 固定8字符长度，便于日志解析软件按列提取
2. 分层结构（CORE/COMM/SENS/CTRL/DATA/SERV/UTIL），便于分类统计
3. 英文缩写避免编码问题，支持国际化
4. 数据类型标识（[GPS_POS]、[IMU_ATT]等）便于自动化数据提取
5. 标准化格式便于批量解析和统计分析

日志解析软件可以使用的过滤模式：
- 按模块过滤：grep "SENS_GPS" logfile.txt
- 按数据类型过滤：grep "\[GPS_POS\]" logfile.txt  
- 按时间范围过滤：awk '/2024-01-01 10:00:00/,/2024-01-01 11:00:00/' logfile.txt
- 提取特定数值：grep -o "speed=[0-9.]*" logfile.txt
- 统计错误次数：grep -c "\[ERR_STAT\]" logfile.txt
- 提取传感器数据：grep "\[GPS_POS\]\|\[IMU_ATT\]\|\[WND_SPD\]" logfile.txt

兼容性说明：
现有代码可以继续使用原有的模块名（如THREAD8_MODULE），系统会自动映射到新的标准名称。
建议在新代码中直接使用新的标准名称，逐步迁移现有代码。
*/

#endif /* LOG_UTILS_H */ 